package com.example.drainage.util;

import java.util.List;
import java.util.Map;

import io.realm.Realm;
import io.realm.RealmModel;
import io.realm.RealmObject;
import io.realm.RealmQuery;
import io.realm.RealmResults;
import io.realm.Sort;


/**
 * 描述：同步访问数据实现
 * 在主线程使用,Realm速度足够快,即使在主线程使用直接使用同步访问也是没有问题的
 * 使用方式请参照 Sample
 *
 * @author 创建人 ：guokunhu
 * @version 1.0
 * @package 包名 ：com.augurit.agmobile.patrolcore.common.database
 * @createTime 创建时间 ：2017/10/17
 * @modifyBy 修改人 ：guokunhu
 * @modifyTime 修改时间 ：2017/10/17
 * @modifyMemo 修改备注：
 */

public class CommonSynDao<T extends RealmModel> {
    private Realm mRealm;

    public CommonSynDao() {
        mRealm = RealmSingleton.getInstance().getRealm();
    }

    public void insert(RealmModel rm)  {
        cancelTransactionIfAlreadyIn();
       //先开启事务
        mRealm.beginTransaction();
        //把对象复制到Realm
        mRealm.copyToRealm(rm);
        //提交事务
        mRealm.commitTransaction();
    }

    public void insert(List list)  {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        mRealm.insert(list);
        mRealm.commitTransaction();
    }


    /**
     * 添加或者修改
     *
     * @param object
     * @return 已经保存的对象
     */
    public <E extends RealmObject> E insertOrUpdate(E object) {
        E savedE = null;
        try {
            mRealm.beginTransaction();
            savedE = mRealm.copyToRealmOrUpdate(object);
            mRealm.commitTransaction();
            return savedE;
        } catch (Exception e) {
            e.printStackTrace();
            mRealm.cancelTransaction();
            return savedE;
        }
    }


    public void delete(Class T, String field, String... values) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        for (String value : values) {
            mRealm.where(T).equalTo(field,value).findAll().deleteAllFromRealm();
        }
        mRealm.commitTransaction();
    }

    public void delete(Class T, String field, Integer... values){
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        for (Integer value : values) {
            mRealm.where(T).equalTo(field,value).findAll().deleteAllFromRealm();
        }
        mRealm.commitTransaction();
    }

    public void delete(RealmQuery query) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        RealmResults all = query.findAll();
        all.deleteAllFromRealm();
        mRealm.commitTransaction();
    }

    public List queryAll(final Class T)  {
        cancelTransactionIfAlreadyIn();
        List<RealmModel> list = null;
        mRealm.beginTransaction();
        RealmResults<RealmModel> results = (RealmResults<RealmModel>) mRealm.where(T).findAll();
        list = mRealm.copyFromRealm(results);
        mRealm.commitTransaction();
        return list;
    }

    public void update(RealmModel rm) {
        cancelTransactionIfAlreadyIn();
        //先开启事务
        mRealm.beginTransaction();
        //把对象更新保存到Realm
        mRealm.copyToRealmOrUpdate(rm);
        //提交事务
        mRealm.commitTransaction();
    }

    public void update(List list)  {
        cancelTransactionIfAlreadyIn();
        //先开启事务
        mRealm.beginTransaction();
        //把对象更新保存到Realm
        mRealm.copyToRealmOrUpdate(list);
        //提交事务
        mRealm.commitTransaction();
    }

    public List query(Class T, Map<String, String> params) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        RealmQuery query = mRealm.where(T);
        for(Object entry : params.entrySet()) {
            Map.Entry<String,String>  mapEntry = (Map.Entry<String,String>)entry;
            query.equalTo(mapEntry.getKey(),mapEntry.getValue());
        }
        RealmResults<T> results = query.findAll();
        mRealm.commitTransaction();
        return mRealm.copyFromRealm(results);
    }

    /**
     * 根据查询条件查询所有结果，并按照sortField进行降序排序
     * @param T 查询的类
     * @param params 查询条件
     * @param sortField 根据哪个字段进行排序
     * @return
     */
    public List query(Class T, Map<String, String> params,String sortField) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        RealmQuery query = mRealm.where(T);
        for(Object entry : params.entrySet()){
            Map.Entry<String,String>  mapEntry = (Map.Entry<String,String>)entry;
            query.equalTo(mapEntry.getKey(),mapEntry.getValue());
        }
        RealmResults<T> results = query.findAll().sort(sortField, Sort.DESCENDING);
        mRealm.commitTransaction();
        return mRealm.copyFromRealm(results);
    }

    public RealmModel queryFirst(Class T, Map<String, String> params) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        RealmQuery query = mRealm.where(T);
        if(params != null && !params.isEmpty()) {
            for (Object entry : params.entrySet()) {
                Map.Entry<String, String> mapEntry = (Map.Entry<String, String>) entry;
                query.equalTo(mapEntry.getKey(), mapEntry.getValue());
            }
        }
        RealmModel result = (RealmModel) query.findFirst();
        mRealm.commitTransaction();
        if (result == null) return null;
        else return mRealm.copyFromRealm(result);
    }

    public void deleteAll(Class T)  {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        mRealm.where(T).findAll().deleteAllFromRealm();
        mRealm.commitTransaction();
    }

    public void delete(Class T, Map<String, String> params) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        RealmQuery query = mRealm.where(T);
        for(Object entry : params.entrySet()){
            Map.Entry<String,String>  mapEntry = (Map.Entry<String,String>)entry;
            query.equalTo(mapEntry.getKey(),mapEntry.getValue());
        }
        query.findAll().deleteAllFromRealm();
        mRealm.commitTransaction();
    }

    public Number getFieldMax(Class T, String numberFiled, Map<String, String> params) {
        cancelTransactionIfAlreadyIn();
        Number max =null ;
        if(params== null || params.isEmpty()){
            mRealm.beginTransaction();
            max = mRealm.where(T).findAll().max(numberFiled);
            mRealm.commitTransaction();
        }else {
            mRealm.beginTransaction();
            RealmQuery query = mRealm.where(T);
            for(Object entry : params.entrySet()){
                Map.Entry<String,String>  mapEntry = (Map.Entry<String,String>)entry;
                query.equalTo(mapEntry.getKey(),mapEntry.getValue());
            }
            max =query.findAll().max(numberFiled);
            mRealm.commitTransaction();
        }
        return max;
    }

    public Number getFieldMin(Class T, String numberFiled, Map<String, String> params) {
        cancelTransactionIfAlreadyIn();
        Number min =null ;
        if(params== null || params.isEmpty()){
            mRealm.beginTransaction();
            min = mRealm.where(T).findAll().min(numberFiled);
            mRealm.commitTransaction();
        }else {
            mRealm.beginTransaction();
            RealmQuery query = mRealm.where(T);
            for(Object entry : params.entrySet()){
                Map.Entry<String,String>  mapEntry = (Map.Entry<String,String>)entry;
                query.equalTo(mapEntry.getKey(),mapEntry.getValue());
            }
            min =query.findAll().min(numberFiled);
            mRealm.commitTransaction();
        }
        return min;
    }

    public int getCountByParams(Class T, Map<String, String> params) {
        cancelTransactionIfAlreadyIn();
        int count=0;
        if(params== null || params.isEmpty()){
            mRealm.beginTransaction();
            count = mRealm.where(T).findAll().size();
            mRealm.commitTransaction();
        }else {
            mRealm.beginTransaction();
            RealmQuery query = mRealm.where(T);
            for(Object entry : params.entrySet()){
                Map.Entry<String,String>  mapEntry = (Map.Entry<String,String>)entry;
                query.equalTo(mapEntry.getKey(),mapEntry.getValue());
            }
            count =query.findAll().size();
            mRealm.commitTransaction();
        }
        return count;
    }

    public void clearDatabase() {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        mRealm.deleteAll();
        mRealm.commitTransaction();
    }

    public <E extends RealmModel> RealmQuery<E> getQuery(Class<E> clazz) {
        return mRealm.where(clazz);
    }

    public <E extends RealmModel> List<E> getEntityByQuery(RealmQuery<E> query) {
        cancelTransactionIfAlreadyIn();
        mRealm.beginTransaction();
        RealmResults<E> all = query.findAll();
        mRealm.commitTransaction();
        return mRealm.copyFromRealm(all);
    }

    private void cancelTransactionIfAlreadyIn() {
        if (mRealm.isInTransaction()) {
            mRealm.cancelTransaction();
        }
    }
}
